#pragma once
#include <iostream>
#include <string>
#include <cstdlib>
#include <cstring>
#include <unistd.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <pthread.h>
#include <signal.h>
#include <signal.h>
#include "log.hpp"
#include "ThreadPool.hpp"
#include "Task.hpp"
#include "Daemon.hpp"

Log lg;

int defaultport = 8888;
std::string defaultip = "0.0.0.0";
int defaultsockfd = -1;
const int backlog = 10;

enum
{
    SOCK_ERR = 1,
    BIND_ERR,
    LISTEN_ERR
};

class Tcpserver;

class ThreadData
{
public:
    ThreadData(int fd, const uint16_t &port, const std::string &ip, Tcpserver *t)
        : sockfd(fd), clinetport(port), clientip(ip), tcvr(t)
    {
    }

public:
    int sockfd;
    uint16_t clinetport;
    std::string clientip;
    Tcpserver *tcvr;
};

class Tcpserver
{
public:
    Tcpserver(int port = defaultport, std::string ip = defaultip)
        : _port(port), _ip(ip), listensock(defaultsockfd)
    {
    }
    // void InitServer()
    // {
    //     // 1. 打印所有参数（确认传参是否正确）
    //     lg(Info, "InitServer: port=%d, ip=%s", _port, _ip.c_str());

    //     // 2. 创建套接字
    //     listensock = socket(AF_INET, SOCK_STREAM, 0);
    //     if (listensock < 0)
    //     {
    //         lg(Fatal, "socket error, errno:%d, errstring:%s", errno, strerror(errno));
    //         exit(SOCK_ERR);
    //     }
    //     lg(Info, "socket created: listensock=%d", listensock); // 看是否创建成功

    //     // 3. 加 SO_REUSEADDR（必须取消注释！）
    //     int opt = 1;
    //     int sock_opt_ret = setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    //     if (sock_opt_ret < 0)
    //     {
    //         lg(Warning, "setsockopt SO_REUSEADDR error: %d, %s", errno, strerror(errno));
    //     }
    //     else
    //     {
    //         lg(Info, "setsockopt SO_REUSEADDR success"); // 确认是否执行
    //     }

    //     // 4. 初始化地址
    //     struct sockaddr_in local;
    //     bzero(&local, sizeof(local));
    //     local.sin_family = AF_INET;
    //     local.sin_port = htons(_port);

    //     // 替换 inet_aton，直接绑定所有IP（先绕开IP问题）
    //     local.sin_addr.s_addr = INADDR_ANY;
    //     lg(Info, "bind to INADDR_ANY (ip=%s will be ignored)", _ip.c_str());

    //     // 5. 绑定
    //     socklen_t len = sizeof(local);
    //     int bind_ret = bind(listensock, (struct sockaddr *)&local, len);
    //     if (bind_ret < 0)
    //     {
    //         // 打印详细错误（必看！）
    //         lg(Fatal, "bind error, errno:%d, errstring:%s, port=%d", errno, strerror(errno), _port);
    //         exit(BIND_ERR);
    //     }
    //     lg(Info, "bind success, listensock=%d, port=%d", listensock, _port);
    // }
    void InitServer()
    {
        // 创建套接字
        listensock = socket(AF_INET, SOCK_STREAM, 0);
        if (listensock < 0)
        {
            lg(Fatal, "socket error,errno:%d,errstring:%s", errno, strerror(errno));
            exit(SOCK_ERR);
        }
        // int opt = 1;
        // if (setsockopt(listensock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt)) < 0)
        // {
        //     lg(Warning, "setsockopt SO_REUSEADDR error: %d, %s", errno, strerror(errno));
        // }
        // 初始化
        struct sockaddr_in local;
        bzero(&local, sizeof(local));
        local.sin_family = AF_INET;
        local.sin_port = htons(_port);
        inet_aton(_ip.c_str(), &(local.sin_addr));
        // 绑定
        // socklen_t len = sizeof(local);
        if (bind(listensock, (struct sockaddr *)&local, sizeof(local)) < 0)
        {
            lg(Fatal, "bind error, errno:%d,strstring:%s", errno, strerror(errno));
            exit(BIND_ERR);
        }
        lg(Info, "bind success,listensock:%d", listensock);

        // 监听
        if (listen(listensock, backlog) < 0)
        {
            lg(Fatal, "listen error,errno:%d,strstring:%s", errno, strerror(errno));
            exit(LISTEN_ERR);
        }
        lg(Info, "listen success,listensock:%d", listensock);
    }

    // static void*Mythread(void*args)
    // {
    //     pthread_detach(pthread_self());
    //     ThreadData*td=static_cast<ThreadData*>(args);
    //     td->tcvr->Service(td->sockfd,td->clientip,td->clinetport);
    //     delete(td);
    //     return nullptr;
    // }
    void Start()
    {
        // Daemon();
        lg(Info, "tcpserver is runing...");
        ThreadPool<Task>::GetInstance()->Start();
        while (true)
        {
            // 1.获取新连接accept
            struct sockaddr_in client;
            socklen_t len = sizeof(client);
            int sockfd = accept(listensock, (struct sockaddr *)&client, &len);
            if (sockfd < 0)
            {
                lg(Warning, "accept error,errno:%%d,errstring:%s", errno, strerror(errno));
                continue;
            }

            // 网络字节序转主机字节序 ntohs
            uint16_t clientport = ntohs(client.sin_port);
            // 客户端端口转成字符串格式（eg:->192.168.1.1） inet_ntop
            char clientip[32];
            inet_ntop(AF_INET, &(client.sin_addr), clientip, sizeof(clientip));
            // 2.根据新连接进行通信
            lg(Info, "get a new link...sockfd:%d,clientip:%s,clientport:%d", sockfd, clientip, clientport);
            // version 1 单进程版
            // Service(sockfd, clientip, clientport);
            // close(sockfd);

            // 版本二：多进程版
            // 多进程并发模型，通过两次fork解决僵尸进程问题，让每个客户端连接独立运行
            // pid_t id = fork();
            // if (id == 0) // child
            // {
            //     // listensock是父进程用于listen的套接字
            //     close(listensock);
            //     if (fork() > 0)
            //         exit(0);
            //     // 孙子进程处理客户端通信
            //     Service(sockfd, clientip, clientport);
            //     close(sockfd);
            //     exit(0);
            // }
            // // 父进程在子进程处理客户端时，不需要sockfd(已交给子进程/孙子进程)，关闭避免文件描述符泄漏
            // close(sockfd);
            // pid_t rid = waitpid(id, nullptr, 0);
            // (void)rid;

            // 版本三：多线程版
            // ThreadData*td=new ThreadData(sockfd,clientport,clientip,this);
            // pthread_t tid;
            // pthread_create(&tid,nullptr,Mythread,td);

            // 版本四：线程池版
            std::cout << "3333" << std::endl;

            // Task t(sockfd, clientport, clientip);
           auto task=std::make_shared<Task>(sockfd, clientport, clientip);
           std::cout<<"Task address in Start:"<<task.get()<<std::endl;
            std::cout << "444" << std::endl;

            ThreadPool<Task>::GetInstance()->Push(task);
            std::cout << "777" << std::endl;

            // t.Run();
        }
    }
    // void Service(int sockfd, const std::string &clientip, const uint16_t &clientport)
    // {
    //     char buffer[4096];
    //     while (true)
    //     {
    //         ssize_t n = read(sockfd, buffer, sizeof(buffer));
    //         if (n > 0)
    //         {
    //             buffer[n] = 0;
    //             std::cout << "client say# " << buffer << std::endl;
    //             std::string echo_string = "server echo# ";
    //             echo_string += buffer;
    //             write(sockfd, buffer, n);
    //         }
    //         else if (n == 0)
    //         {
    //             lg(Info, "%s:%d quit,server close sockfd:%d", clientip.c_str(), clientport, sockfd);
    //             break;
    //         }
    //         else
    //         {
    //             lg(Warning, "read error,sockfd:%d,client ip:%s,clientport:%d", sockfd, clientip.c_str(), clientport);
    //             break;
    //         }
    //     }
    // }

    ~Tcpserver()
    {
                   std::cout<<"Task address in ~Task:"<<this<<std::endl;

    }

private:
    int listensock;
    uint16_t _port;
    std::string _ip;
};